package com.liruo.learn.spring.mvc.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.SessionCookieConfig;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Stream;

/**
 * @Author:liruo
 * @Date:2023-03-10-21:46:17
 * @Desc
 */
@CrossOrigin(origins="http://localhost:3000", methods = RequestMethod.POST, allowCredentials = "true")
@RestController
@RequestMapping("/cors")
@Slf4j
public class TestCorsController {
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class User{
        private Long id;
        private String name;
        private Integer age;
    }
    List<User> users = Stream.of(new User(1L,"u1", 1), new User(2L,"u2", 2)).toList();
    @PostMapping("/1")
    public List<User> get1(HttpServletRequest req, HttpSession session, HttpServletResponse resp){
        log.info("session id={}, CreationTime={},  LastAccessedTime={}, MaxInactiveInterval={}",
                session.getId(),
                session.getCreationTime(),
                session.getLastAccessedTime(),
                session.getMaxInactiveInterval()
        );
        SessionCookieConfig sessionCookieConfig = session.getServletContext().getSessionCookieConfig();
        if(sessionCookieConfig != null){
            log.info("sessionCookieConfig");
            invokeGets(new Object[]{sessionCookieConfig});
        }
        ArrayList<String> arrayList = new ArrayList<>();
        Enumeration<String> sessionAttrNames = session.getAttributeNames();
        while(sessionAttrNames.hasMoreElements()){
            arrayList.add(session.getAttribute(sessionAttrNames.nextElement()).toString());
        }
        log.info("session attributes= {}", String.join("\n", arrayList));

        Cookie[] cookies = req.getCookies();
        if(!ArrayUtils.isEmpty(cookies)){
            log.info("has {} cookies", cookies.length);
            invokeGets(cookies);
        }
        for (Cookie cookie : cookies) {
            if(cookie.getName().equals("JSESSIONID")){
                try {
                    log.info("{}", new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(cookie));
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        session.setAttribute("session", "attr");
        long hasMyCookie = Arrays.stream(cookies).filter(c -> c.getName().equals("myCookie")).count();
        if(hasMyCookie != 1){
            Cookie cookie = new Cookie("myCookie", "myValue");
            cookie.setHttpOnly(false);
            cookie.setDomain("localhost");
            cookie.setMaxAge(3600);
            resp.addCookie(cookie);
        }
        return users;
    }

    private static void invokeGets(Object[] objs) {
        for (Object obj : objs) {
            ReflectionUtils.doWithMethods(obj.getClass(), method -> {
                if((method.getName().startsWith("get") || method.getName().startsWith("is"))
                        && method.getParameterCount() == 0 && method.trySetAccessible()){
                    try {
                        log.info("invoke {} return = {}", method.getName(), method.invoke(obj));
                    } catch (InvocationTargetException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
    }
}
